home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / MiscKit1.7.1 / MiscKit / Source / MiscKit / MiscStringCompat.m < prev    next >
Encoding:
Text File  |  1995-07-25  |  13.4 KB  |  531 lines

  1. //
  2. //    MiscStringCompat.m
  3. //        Written by Don Yacktman Copyright (c) 1993 by Don Yacktman.
  4. //                Version 1.95  All rights reserved.
  5. //        This notice may not be removed from this source code.
  6. //
  7. //    This object is included in the MiscKit by permission from the author
  8. //    and its use is governed by the MiscKit license, found in the file
  9. //    "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
  10. //    for a list of all applicable permissions and restrictions.
  11. //    
  12.  
  13. #import <misckit/MiscString.h>
  14.  
  15. @implementation MiscString(Compat)
  16.  
  17. // This category includes methods to make the MiscString compatible
  18. // with other existing string classes.  This way, you can easily
  19. // replace your crufty old string class with a MiscString without
  20. // having to change the code.  Most methods are covers which simply
  21. // call the appropriate existing MiscString function.  The majority
  22. // of these methods actually add compatability with the MOString class,
  23. // but there is other stuff in here, too...
  24.  
  25. // None of the methods in this category add functionality; they are wrappers
  26. // around existing methods which allow programmers to use calls associated
  27. // with other string classes on the MiscString.  When I add compatability
  28. // with string classes, if there is a function that adds functionality, I
  29. // write a compatible method and place it into another category.  Only
  30. // redundant methods are in this category, which is why they are not
  31. // detailed in the documentation.
  32.  
  33. // If you have some _other_ string class, and would like to see
  34. // compatibility methods added to the MiscString to support that
  35. // class, too, let us know!
  36.  
  37. // Most of these methods are derived by Don Yacktman from code written
  38. // by Mike Ferris and David Lehn.
  39.  
  40. - takeStringValue:sender { return [self takeStringValueFrom:sender]; }
  41.  
  42. - clear
  43. {
  44.     [self freeString];
  45.     return self;
  46. }
  47.  
  48. - ( const char* ) string
  49. {
  50.    return [self stringValue];
  51. }
  52.  
  53. - setString: ( const char *) aString
  54. {
  55.     [self setStringValue:aString];
  56.     return self;
  57. }
  58.  
  59. - replaceChar: ( char ) aChar withChar: ( char ) replaceChar
  60. {
  61.     return [self replaceEveryInstanceOfChar:aChar withChar:replaceChar];
  62. }
  63.  
  64. - addToEndOfString: ( const char *) aString
  65. {
  66.     [self cat:aString];
  67.     return self;
  68. }
  69.  
  70. - addToFrontOfString: ( const char *) aString
  71. {
  72.     [self insert:aString at:0];
  73.     return self;
  74. }
  75.  
  76. - addCharToEndOfString: ( char ) aChar
  77. {
  78.     [self addChar:aChar];
  79.     return self;
  80. }
  81.  
  82. - addCharToFrontOfString: ( char ) aChar
  83. {
  84.     [self insertChar:aChar at:0];
  85.     return self;
  86. }
  87.  
  88. - ( int ) numberFields
  89. {
  90.     return [self numWords];
  91. }
  92.  
  93. - ( char * ) nthField: ( int ) fieldNumber useAsDelimiter: ( char ) c
  94. {
  95.     char * field;
  96.     id fieldString = [ self extractPart:(fieldNumber) useAsDelimiter:c ];
  97.     if (!fieldString) return NULL;
  98.     field = NXZoneMalloc( [ self zone ], [ fieldString length ] + 1 );
  99.     strcpy(field, [ fieldString stringValue ]);
  100.     [fieldString free];
  101.     return field;
  102. }
  103.  
  104. - ( char * ) nthField: ( int ) fieldNumber
  105. {    // have to do all this garbage to make sure we (1) don't leak memory
  106.     // and (2) we don't smash the stringValueAndFree buffer.  (Otherwise
  107.     // I would just use it, but that would make the MiscString badly
  108.     // non-reentrant.)  This works, anyway...though the obvious
  109.     // implementation would be this:
  110.     //
  111.     //        return [[self wordNum:fieldNumber] stringValueAndFree];
  112.  
  113.     static id tempBuffer = nil; id temp;
  114.  
  115.     if (!tempBuffer) tempBuffer = [MiscString new];
  116.     temp = [self wordNum:fieldNumber];
  117.     [tempBuffer setStringValue:[temp stringValue]];
  118.     [temp free];
  119.     return (char *)[tempBuffer stringValue];
  120. }
  121.  
  122. // this one kind of adds functionality, but by naming conventions it still
  123. // makes sense to put it here.
  124. - ( char * ) nthQuotedField: ( int ) fieldNumber
  125. {
  126.     return [ self nthField:fieldNumber*2 useAsDelimiter:'"' ];
  127. }
  128.  
  129. - ( char * ) lastField
  130. {
  131.     char * field;
  132.     id str = [ self extractPart:MISC_STRING_LAST useAsDelimiter:' ' ];
  133.     field = NXZoneMalloc([self zone], [str length] + 1);
  134.     strcpy(field, [str stringValue]);
  135.     [str free];
  136.     return field;
  137. }
  138.  
  139. - ( char * ) firstField
  140. {
  141.     char * field;
  142.     id str = [ self extractPart:MISC_STRING_FIRST useAsDelimiter:' ' ];
  143.     field = NXZoneMalloc([self zone], [str length] + 1);
  144.     strcpy(field, [str stringValue]);
  145.     [str free];
  146.     return field;
  147. }
  148.  
  149. - addStrings: ( const char *) fields,  ...
  150. {
  151.     va_list ptr;
  152.   
  153.     va_start( ptr, fields );
  154.     [self catStrings:fields, ptr];
  155.     va_end( ptr );       
  156.     return self;
  157. }
  158.  
  159. - replaceEveryInstanceOfChar:(char)aChar withChar:(char)replaceChar
  160. {
  161.     return [self replaceEveryOccurrenceOfChar:aChar
  162.             withChar:replaceChar caseSensitive:YES];
  163. }
  164.  
  165. - replaceEveryInstanceOfChar:(char)aChar with:(char)replaceChar
  166. {
  167.     return [self replaceEveryOccurrenceOfChar:aChar
  168.             withChar:replaceChar caseSensitive:YES];
  169. }
  170.  
  171. // The rest of the methods here are for compatability with the MOString
  172. // from the MOKit.
  173.  
  174. // warning:  the following MOString methods clash with MiscString methods
  175. //    of the same name.  You will have to check your code for uses of these
  176. //    methods and fix them appropriately to avoid serious problems.
  177. //    Group 1:  MOString wants string object, MiscString wants char *
  178. //        -insert:stringObject at:(int)position
  179. //        -cat:stringObject
  180. //    Note also that the MiscString doesn't support the unique string
  181. //    concept, so it cannot become a unique string.  Perhaps in the
  182. //    future there will be a MiscUniqueString class; I prefer that approach
  183. //    myself.  At any rate, this shouldn't affect the functionality when
  184. // using the MiscString compatibly.
  185.  
  186. - convertToUpper
  187. {
  188.     return [self toUpper];
  189. }
  190.  
  191. - convertToLower
  192. {
  193.     return [self toLower];
  194. }
  195.  
  196. - (int)replaceAllOccurrencesOfChar:(char)oldChar with:(char)newChar
  197. {
  198.     [self replaceEveryOccurrenceOfChar:oldChar withChar:newChar];
  199.     return 0; // this information isn't available so we'll just return zero
  200. }
  201.  
  202. - (char)replaceCharAt:(int)index with:(char)newChar
  203. {
  204.     char tempChar = [self charAt:index];
  205.     [self replaceCharAt:index withChar:newChar];
  206.     return tempChar; 
  207. }
  208.  
  209. - insertStringValue:(const char *)s at:(int)position
  210. {
  211.     [self insert:s at:position];
  212.     return self;
  213. }
  214.  
  215. - preCatStringValue:(const char *)s
  216. {
  217.     return [self insert:s at:0];
  218. }
  219.  
  220. - preCat:stringObject
  221. {
  222.     return [self insertString:stringObject];
  223. }
  224.  
  225. - preCatFromFormat:(const char *)format, ...
  226. // Prepends the given format string after formatting before the contents
  227. // of the receiver.
  228. {
  229.     va_list param_list;
  230.  
  231.     va_start(param_list, format);
  232.     [self insertFromFormat:format, param_list];
  233.     va_end(param_list);
  234.     return self;
  235. }
  236.  
  237. - catStringValue:(const char *)s
  238. {
  239.     return [self cat:s];
  240. }
  241.  
  242. - (int)compare:stringObject caseSensitive:(BOOL)flag
  243. {
  244.     return [self compare:stringObject caseSensitive:flag 
  245.                     length:-1 withTable:NULL];
  246. }
  247.  
  248. - (int)compare:stringObject caseSensitive:(BOOL)flag length:(int)len
  249. {
  250.     return [self compare:stringObject caseSensitive:flag 
  251.                     length:len withTable:NULL];
  252. }
  253.  
  254. - (int)compare:stringObject caseSensitive:(BOOL)flag length:(int)len 
  255.             withTable:(NXStringOrderTable *)table
  256. {
  257.     int ret;
  258.     NXStringOrderTable *realTable = [self stringOrderTable]; // temp save
  259.     [self setStringOrderTable:table];
  260.     ret = [self compareTo:stringObject n:len caseSensitive:flag];
  261.     [self setStringOrderTable:realTable];
  262.     return ret;
  263. }
  264.  
  265. - (int)compareStr:(const char *)s
  266. {
  267.     return [self compareStr:s caseSensitive:YES length:-1 withTable:NULL];
  268. }
  269.  
  270. - (int)compareStr:(const char *)s caseSensitive:(BOOL)flag
  271. {
  272.     return [self compareStr:s caseSensitive:flag length:-1 withTable:NULL];
  273. }
  274.  
  275. - (int)compareStr:(const char *)s caseSensitive:(BOOL)flag length:(int)len
  276. {
  277.     return [self compareStr:s caseSensitive:flag length:len withTable:NULL];
  278. }
  279.  
  280. - (int)compareStr:(const char *)s caseSensitive:(BOOL)flag length:(int)len
  281.             withTable:(NXStringOrderTable *)table
  282. {
  283.     id ss = [[self class] newWithString:s];
  284.     int ret = [self compare:ss caseSensitive:flag length:len withTable:table];
  285.     [ss free];
  286.     return ret;
  287. }
  288.  
  289. - (int)endCompare:stringObject caseSensitive:(BOOL)flag
  290. {
  291.     return [self endCompare:stringObject 
  292.                     caseSensitive:flag length:-1 withTable:NULL];
  293. }
  294.  
  295. - (int)endCompare:stringObject caseSensitive:(BOOL)flag length:(int)len
  296. {
  297.     return [self endCompare:stringObject 
  298.                     caseSensitive:flag length:len withTable:NULL];
  299. }
  300.  
  301. - (int)endCompare:stringObject caseSensitive:(BOOL)flag length:(int)len 
  302.             withTable:(NXStringOrderTable *)table
  303. {
  304.     int ret;
  305.     NXStringOrderTable *realTable = [self stringOrderTable]; // temp save
  306.     [self setStringOrderTable:table];
  307.     ret = [self endCompareTo:stringObject n:len caseSensitive:flag];
  308.     [self setStringOrderTable:realTable];
  309.     return ret;
  310. }
  311.  
  312. - (int)endCompareStr:(const char *)s
  313. {
  314.     return [self endCompareStr:s caseSensitive:YES 
  315.                 length:-1 withTable:NULL];
  316. }
  317.  
  318. - (int)endCompareStr:(const char *)s caseSensitive:(BOOL)flag
  319. {
  320.     return [self endCompareStr:s caseSensitive:flag 
  321.                 length:-1 withTable:NULL];
  322. }
  323.  
  324. - (int)endCompareStr:(const char *)s caseSensitive:(BOOL)flag 
  325.             length:(int)len
  326. {
  327.     return [self endCompareStr:s caseSensitive:flag 
  328.                 length:len withTable:NULL];
  329. }
  330.  
  331. - (int)endCompareStr:(const char *)s caseSensitive:(BOOL)flag 
  332.             length:(int)len withTable:(NXStringOrderTable *)table
  333. {
  334.     id ss = [[self class] newWithString:s];
  335.     int ret = [self endCompare:ss caseSensitive:flag
  336.             length:len withTable:table];
  337.     [ss free];
  338.     return ret;
  339. }
  340.  
  341. - substringFrom:(int)start to:(int)end
  342. {
  343.     return [self midFrom:start to:end];
  344. }
  345.  
  346. - (int)positionOf:(char)aChar nthOccurrence:(int)n
  347. {
  348.     if (n<0) return [self rspotOf:aChar occurrenceNum:(-n) caseSensitive:YES];
  349.     return [self spotOf:aChar occurrenceNum:n caseSensitive:YES];
  350. }
  351.  
  352. - (int)countOccurrencesOf:(char)aChar
  353. {
  354.     return [self numOfChar:aChar caseSensitive:YES];
  355. }
  356.  
  357. - (size_t)strlen
  358. {
  359.     return length;
  360. }
  361.  
  362. - (const char *)strcpy:(const char *)s
  363. {
  364.     [self setStringValue:s];
  365.     return buffer;
  366. }
  367.  
  368. - (const char *)strncpy:(const char *)s :(size_t)n
  369. {
  370.     [self setStringValue:s n:(int)n fromZone:[self zone]];
  371.     return buffer;
  372. }
  373.  
  374. - (const char *)strcat:(const char *)s
  375. {
  376.     [self cat:s];
  377.     return buffer;
  378. }
  379.  
  380. - (const char *)strncat:(const char *)s :(size_t)n
  381. {
  382.     [self cat:s n:n fromZone:[self zone]];
  383.     return buffer;
  384. }
  385.  
  386. - (int)strcmp:(const char *)s
  387. {
  388.     if ((!buffer) || (!s)) return -2;
  389.     return strcmp(buffer, s);
  390. }
  391.  
  392. - (int)strncmp:(const char *)s :(size_t)n
  393. {
  394.     if ((!buffer) || (!s)) return -2;
  395.     return strncmp(buffer, s, n);
  396. }
  397.  
  398. - (const char *)strchr:(char)aChar
  399. {
  400.     if (buffer) return NULL;
  401.     return strchr(buffer, aChar);
  402. }
  403.  
  404. - (const char *)strrchr:(char)aChar
  405. {
  406.     if (!buffer) return NULL;
  407.     return strrchr(buffer, aChar);
  408. }
  409.  
  410. - (const char *)strpbrk:(const char *)breakChars
  411. {
  412.     if ((!buffer) || (!breakChars)) return NULL;
  413.     return strpbrk(buffer, breakChars);
  414. }
  415.  
  416. - (size_t)strspn:(const char *)acceptableChars
  417. {
  418.     if ((!buffer) || (!acceptableChars)) return -1;
  419.     return strspn(buffer, acceptableChars);
  420. }
  421.  
  422. - (size_t)strcspn:(const char *)breakChars
  423. {
  424.     if ((!buffer) || (!breakChars)) return 0;
  425.     return strcspn(buffer, breakChars);
  426. }
  427.  
  428. - initStringValue:(const char *)s
  429. {
  430.     return [self initString:s];
  431. }
  432.  
  433. - initStringValueNoCopy:(char *)s
  434. {    // we still copy it anyway; this could be implemented for effect a speedup
  435.     // if it makes that much difference...
  436.     return [self initString:s];
  437. }
  438.  
  439. - initStringValueNoCopy:(char *)s shouldFree:(BOOL)flag
  440. {
  441.     id ret = [self initString:s];
  442.     if (flag) NX_FREE(s);
  443.     return ret;
  444. }
  445.  
  446. - initStringValueUnique:(const char *)s
  447. {
  448.     return [self initString:s];
  449. }
  450.  
  451. - deepCopy
  452. {
  453.     return [self deepCopyFromZone:[self zone]];
  454. }
  455.  
  456. - deepCopyFromZone:(NXZone *)zone
  457. { // our copy from zone IS deep already...
  458.     return [self copyFromZone:zone];
  459. }
  460.  
  461. - shallowCopy
  462. {
  463.     return [self shallowCopyFromZone:[self zone]];
  464. }
  465.  
  466. - shallowCopyFromZone:(NXZone *)zone
  467. { // our copy from zone IS deep already...
  468.     return [self copyFromZone:zone];
  469. }
  470.  
  471. - setStringValueNoCopy:(const char *)s
  472. {    // we set the string value by copying anyway.
  473.     return [self setStringValue:s];
  474. }
  475.  
  476. - setStringValueNoCopy:(char *)s shouldFree:(BOOL)flag
  477. {
  478.     id ret = [self setStringValue:s];
  479.     if (flag) NX_FREE(s);
  480.     return ret;
  481. }
  482.  
  483. - setStringValueUnique:(const char *)s { return [self setStringValue:s]; }
  484. - setNull { return [self freeString]; }
  485. - makeUnique { return self; } // we don't support this at all.
  486. - setShouldFree:(BOOL)flag { return self; }
  487. - (unsigned int)count { return length; }
  488. - (BOOL)isNull { return [self emptyString]; }
  489. - (BOOL)isEmpty { return [self emptyString]; }
  490. - (BOOL)isUnique { return NO; }
  491. - (BOOL)shouldFree { return YES; }
  492.  
  493.  
  494.  
  495.  
  496. // MOPathString methods
  497. - (int)numberOfComponents { return [self numberOfPathComponents]; }
  498. - componentAt:(int)index { return [self pathComponentAt:index]; }
  499. - file { return [self fileName]; }
  500. - directory { return [self pathName]; }
  501. - (const char *)path { return [self stringValue]; }
  502. - (BOOL)isRelative { return [self isRelativePath]; }
  503. - (BOOL)isAbsolute { return [self isAbsolutePath]; }
  504. - (BOOL)isDirectory { return [self isFileOfType:Misc_Directory]; }
  505. - (BOOL)isPlainFile { return [self isFileOfType:Misc_PlainFile]; }
  506. - (BOOL)isSymbolicLink { return [self isFileOfType:Misc_SymbolicLink]; }
  507. - (BOOL)isCharacterSpecial { return [self isFileOfType:Misc_CharacterSpecial]; }
  508. - (BOOL)isBlockSpecial { return [self isFileOfType:Misc_BlockSpecial]; }
  509. - (BOOL)isSocket { return [self isFileOfType:Misc_Socket]; }
  510. - setPathSeparator:(char)c { return self; } // NO OP
  511. - setExtensionSeparator:(char)c { return self; } // NO OP
  512. - (char)pathSeparator { return '/'; }
  513. - (char)extensionSeparator { return '.'; }
  514. - setPath:(const char *)path { return [self setStringValue:path]; }
  515. - initPath:(const char *)path { return [self initStringValue:path]; }
  516. - (char *)buffer { return buffer; } // be careful with this!  don't muck it up!
  517.  
  518.  
  519. // NSString emulations.  First two courtesy of Scott Anguish:
  520. - (BOOL)hasPrefix:(const char *)value
  521. {
  522.     return ([self cmp:value n:strlen(value)]==0);
  523. }
  524.  
  525. - (BOOL)hasPrefixString:value
  526. {
  527.     return ([self compareTo:value n:[value length]]==0);
  528. }
  529.  
  530. @end
  531.